package com.nnnu.wsnackshop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nnnu.wsnackshop.exception.ObjectException;
import com.nnnu.wsnackshop.mapper.UsersMapper;
import com.nnnu.wsnackshop.pojo.dto.AddAddressDTO;
import com.nnnu.wsnackshop.pojo.dto.AddressPageDTO;
import com.nnnu.wsnackshop.pojo.dto.UpdateAddressDTO;
import com.nnnu.wsnackshop.pojo.entity.Addresses;
import com.nnnu.wsnackshop.mapper.AddressesMapper;
import com.nnnu.wsnackshop.pojo.vo.AddressVO;
import com.nnnu.wsnackshop.result.PageResult;
import com.nnnu.wsnackshop.service.IAddressesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 地址表 服务实现类
 * </p>
 *
 * @author zk
 * @since 2025-05-14
 */
@Service
@RequiredArgsConstructor
public class AddressesServiceImpl extends ServiceImpl<AddressesMapper, Addresses> implements IAddressesService {
    private final UsersMapper usersMapper;

    private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public PageResult<AddressVO> pageAddresses(AddressPageDTO dto) {
        Page<Addresses> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<Addresses> qw = Wrappers.<Addresses>lambdaQuery()
                .eq(dto.getUserId() != null, Addresses::getUserId, dto.getUserId())
                .orderByDesc(Addresses::getIsDefault)
                .orderByDesc(Addresses::getId);

        Page<Addresses> r = baseMapper.selectPage(page, qw);
        List<AddressVO> vos = r.getRecords().stream().map(addr -> {
            AddressVO vo = BeanUtil.toBean(addr, AddressVO.class);
            vo.setCreatedAt(addr.getCreatedAt().format(FMT));
            vo.setUpdatedAt(addr.getUpdatedAt().format(FMT));
            return vo;
        }).collect(Collectors.toList());

        return PageResult.<AddressVO>builder().total(r.getTotal()).items(vos).build();
    }

    @Override
    public AddressVO getAddressDetail(Long id) {
        Addresses addr = baseMapper.selectById(id);
        if (addr == null)
            throw new ObjectException("地址不存在: " + id);
        AddressVO vo = BeanUtil.toBean(addr, AddressVO.class);
        vo.setCreatedAt(addr.getCreatedAt().format(FMT));
        vo.setUpdatedAt(addr.getUpdatedAt().format(FMT));
        vo.setDetailAddress(addr.getDetail());
        vo.setRecipientPhone(addr.getPhone());
        vo.setRecipientName(addr.getRecipient());
        return vo;
    }

    @Override
    public List<AddressVO> listByUser(Long userId) {
        if (usersMapper.selectById(userId) == null)
            throw new ObjectException("用户不存在: " + userId);

        return baseMapper.selectList(Wrappers.<Addresses>lambdaQuery().eq(Addresses::getUserId, userId)
                .orderByDesc(Addresses::getIsDefault).orderByDesc(Addresses::getId)).stream().map(addr -> {
                    AddressVO vo = BeanUtil.toBean(addr, AddressVO.class);
                    vo.setDetailAddress(addr.getDetail());
                    vo.setRecipientPhone(addr.getPhone());
                    vo.setRecipientName(addr.getRecipient());
                    vo.setCreatedAt(addr.getCreatedAt().format(FMT));
                    vo.setUpdatedAt(addr.getUpdatedAt().format(FMT));
                    return vo;
                }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAddress(@NotNull AddAddressDTO dto) {
        if (usersMapper.selectById(dto.getUserId()) == null)
            throw new ObjectException("用户不存在: " + dto.getUserId());

        // 如果要设为默认，则先把同用户的其他地址都置 0
        if (dto.getIsDefault() != null && dto.getIsDefault() == 1) {
            baseMapper.update(null, Wrappers.<Addresses>lambdaUpdate()
                    .eq(Addresses::getUserId, dto.getUserId())
                    .set(Addresses::getIsDefault, 0));
        }
        Addresses addr = BeanUtil.toBean(dto, Addresses.class);
        baseMapper.insert(addr);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAddress(UpdateAddressDTO dto) {
        Addresses addr = baseMapper.selectById(dto.getId());
        if (addr == null)
            throw new ObjectException("地址不存在: " + dto.getId());
        if (usersMapper.selectById(dto.getUserId()) == null)
            throw new ObjectException("用户不存在: " + dto.getUserId());

        // 互斥默认
        if (dto.getIsDefault() != null && dto.getIsDefault() == 1) {
            baseMapper.update(null, Wrappers.<Addresses>lambdaUpdate()
                    .eq(Addresses::getUserId, dto.getUserId())
                    .ne(Addresses::getId, dto.getId())
                    .set(Addresses::getIsDefault, 0));
        }
        LambdaUpdateWrapper<Addresses> uw = Wrappers.<Addresses>lambdaUpdate().eq(Addresses::getId, dto.getId())
                .set(dto.getDistrict() != null, Addresses::getDistrict, dto.getDistrict())
                .set(dto.getRecipient() != null, Addresses::getRecipient, dto.getRecipient())
                .set(dto.getPhone() != null, Addresses::getPhone, dto.getPhone())
                .set(dto.getProvince() != null, Addresses::getProvince, dto.getProvince())
                .set(dto.getCity() != null, Addresses::getCity, dto.getCity())
                .set(dto.getDetail() != null, Addresses::getDetail, dto.getDetail())
                .set(dto.getLatitude() != null, Addresses::getLatitude, dto.getLatitude())
                .set(dto.getLongitude() != null, Addresses::getLongitude, dto.getLongitude())
                .set(dto.getIsDefault() != null, Addresses::getIsDefault, dto.getIsDefault());
        update(uw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAddresses(List<Long> ids) {
        if (ids == null || ids.isEmpty())
            throw new ObjectException("地址列表为空");
        List<Long> list = ids.stream().distinct().toList();
        List<Long> missing = list.stream().filter(id -> baseMapper.selectById(id) == null).toList();
        if (!missing.isEmpty())
            throw new ObjectException("以下地址不存在: " + missing);
        baseMapper.deleteBatchIds(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setDefaultAddress(Integer userId, Long addressId) {
        // 验证用户是否存在
        if (usersMapper.selectById(userId) == null) {
            throw new ObjectException("用户不存在: " + userId);
        }

        // 验证地址是否存在且属于该用户
        Addresses address = baseMapper.selectById(addressId);
        if (address == null) {
            throw new ObjectException("地址不存在: " + addressId);
        }
        if (!address.getUserId().equals(userId)) {
            throw new ObjectException("地址不属于该用户");
        }

        // 先将该用户的所有地址设为非默认
        baseMapper.update(null, Wrappers.<Addresses>lambdaUpdate()
                .eq(Addresses::getUserId, userId)
                .set(Addresses::getIsDefault, 0));

        // 再将指定地址设为默认
        baseMapper.update(null, Wrappers.<Addresses>lambdaUpdate()
                .eq(Addresses::getId, addressId)
                .set(Addresses::getIsDefault, 1));
    }
}
